
#include <BShape>

#include "member_BShape.h"

using namespace BWE;

#define member					(*(member_BShape*)_ptr)
#define member_allocate()		_ptr = new member_BShape(this)
#define member_release()		delete (member_BShape*)_ptr

BShape::BShape()
{
	member_allocate();
}
BShape::~BShape()
{
	member_release();
}

void BShape::setVisible(bool visible)
{
	if (member.visible != visible)
	{
		member.visible = visible;
		if (visible)
			emit(Signal_Show);
		else
			emit(Signal_Hide);
		emit(Signal_Fresh);
	}
}
bool BShape::visible() const
{
	return member.visible;
}

void BShape::setCollible(bool collible)
{
	if (member.collible)
	{
		member.collible = collible;
	}
}
bool BShape::collible() const
{
	return member.collible;
}

void BShape::move(const BVector& move)
{
	BMatrix matrix = member.matrix;
	matrix.setPosition(matrix.position() + move);
	setMatrix(matrix);
}
void BShape::move(float x, float y, float z)
{
	BMatrix matrix = member.matrix;
	matrix.setPosition(matrix.position() + BVector(x, y, z));
	setMatrix(matrix);
}

void BShape::setPosition(const BVector& position)
{
	BMatrix matrix = member.matrix;
	matrix.setPosition(position);
	setMatrix(matrix);
}
void BShape::setPosition(float x, float y, float z)
{
	BMatrix matrix = member.matrix;
	matrix.setPosition(x, y, z);
	setMatrix(matrix);
}
BVector BShape::position() const
{
	return member.matrix.position();
}

void BShape::setRotate(float rx, float ry, float rz)
{
	BQuater xrotate(rx, BVector(1, 0, 0));
	BQuater yrotate(ry, BVector(0, 1, 0));
	BQuater zrotate(rz, BVector(0, 0, 1));
	BMatrix matrix = member.matrix;
	matrix.setRotate(xrotate * yrotate * zrotate);
	setMatrix(matrix);
}
void BShape::setRotate(const BQuater& quater)
{
	BMatrix matrix = member.matrix;
	matrix.setRotate(quater);
	setMatrix(matrix);
}
BQuater BShape::rotate() const
{
	return member.matrix.rotate();
}

void BShape::setScale(const BVectorf& scale)
{
	BMatrix matrix = member.matrix;
	matrix.setScale(scale);
	setMatrix(matrix);
}
void BShape::setScale(float x, float y, float z)
{
	BMatrix matrix = member.matrix;
	matrix.setScale(x, y, z);
	setMatrix(matrix);
}
BVector BShape::scale() const
{
	return member.matrix.scale();
}

void BShape::setMatrix(const BMatrix& matrix)
{
	if (member.matrix != matrix)
	{
		member.matrix = matrix;
		member.dirtySpace = true;
		emit(Signal_Fresh);
	}
}
const BMatrix& BShape::matrix() const
{
	return member.matrix;
}

const BBox& BShape::box() const
{
	if (member.dirty)
		((BShape*)this)->flush();
	return member.box;
}
const BSpace& BShape::space() const
{
	if (member.dirtySpace)
	{
		BBox box = this->box() * member.matrix;
		member.space.reset(box.v0());
		member.space.expand(box.v1());
		member.space.expand(box.v2());
		member.space.expand(box.v3());
		member.space.expand(box.v4());
		member.space.expand(box.v5());
		member.space.expand(box.v6());
		member.space.expand(box.v7());
		member.dirtySpace = false;
	}
	return member.space;
}

void BShape::setColor(BByte r, BByte g, BByte b, BByte a)
{
	setColor(BColor(r, g, b, a));
}
void BShape::setColor(const BColor& color)
{
	if (member.color != color)
	{
		member.color = color;
		emit(Signal_Fresh);
	}
}
const BColor& BShape::color() const
{
	return member.color;
}

void BShape::setMaterial(BMaterial* material)
{
	if (member.material != material)
	{
		member.material = material;
		emit(Signal_Fresh);
	}
}
BMaterial* BShape::material() const
{
	return member.material.ptr();
}

bool BShape::setTexture(BTexture* texture, int unit)
{
	if (unit > 20)
		return false;
	if (member.textures.size() <= unit)
		member.textures.resize(unit + 1);
	member.textures.set(unit, texture);
	emit(Signal_Fresh);
	return true;
}
BTexture* BShape::texture(int unit) const
{
	return member.textures(unit);
}

void BShape::setProgram(BProgram* program)
{
	if (member.program != program)
	{
		member.program = program;
		emit(Signal_Fresh);
	}
}
BProgram* BShape::program() const
{
	return member.program.ptr();
}

void BShape::setCullBack(bool cullBack)
{
	if (member.cullBack != cullBack)
	{
		member.cullBack = cullBack;
		emit(Signal_Fresh);
	}
}
bool BShape::cullBack() const
{
	return member.cullBack;
}

void BShape::setLighting(bool lighting)
{
	if (member.lighting != lighting)
	{
		member.lighting = lighting;
		emit(Signal_Fresh);
	}
}
bool BShape::lighting() const
{
	return member.lighting;
}

void BShape::setDepthTest(bool depthTest)
{
	if (member.depthTest != depthTest)
	{
		member.depthTest = depthTest;
		emit(Signal_Fresh);
	}
}
bool BShape::depthTest() const
{
	return member.depthTest;
}

void BShape::setLineSmooth(bool lineSmooth)
{
	if (member.lineSmooth != lineSmooth)
	{
		member.lineSmooth = lineSmooth;
		emit(Signal_Fresh);
	}
}
bool BShape::lineSmooth() const
{
	return member.lineSmooth;
}

void BShape::setPolygonSmooth(bool polygonSmooth)
{
	if (member.polygonSmooth != polygonSmooth)
	{
		member.polygonSmooth = polygonSmooth;
		emit(Signal_Fresh);
	}
}
bool BShape::polygonSmooth() const
{
	return member.polygonSmooth;
}

void BShape::setLineWidth(int lineWidth)
{
	if (lineWidth <= 0)
		lineWidth = 1;
	if (member.lineWidth != lineWidth)
	{
		member.lineWidth = lineWidth;
		emit(Signal_Fresh);
	}
}
int BShape::lineWidth() const
{
	return member.lineWidth;
}

void BShape::setNormalize(bool normalize)
{
	if (member.normalize != normalize)
	{
		member.normalize = normalize;
		emit(Signal_Fresh);
	}
}
bool BShape::normalize() const
{
	return member.normalize;
}

void BShape::setPointSmooth(bool pointSmooth)
{
	if (member.pointSmooth != pointSmooth)
	{
		member.pointSmooth = pointSmooth;
		emit(Signal_Fresh);
	}
}
bool BShape::pointSmooth() const
{
	return member.pointSmooth;
}

void BShape::setPointSize(int pointSize)
{
	if (pointSize <= 0)
		pointSize = 1;
	if (member.pointSize != pointSize)
	{
		member.pointSize = pointSize;
		emit(Signal_Fresh);
	}
}
int BShape::pointSize() const
{
	return member.pointSize;
}

void BShape::setTransparent(bool transparent)
{
	if (member.transparent != transparent)
	{
		member.transparent = transparent;
		emit(Signal_Fresh);
	}
}
bool BShape::transparent() const
{
	return member.transparent;
}

void BShape::setPolygonMode(PolygonMode polygonMode)
{
	if (member.polygonMode != polygonMode)
	{
		member.polygonMode = polygonMode;
		emit(Signal_Fresh);
	}
}
PolygonMode BShape::polygonMode() const
{
	return (PolygonMode)member.polygonMode;
}

void BShape::dirty()
{
	member.dirty = true;
	emit(Signal_Dirty);
}
void BShape::flush()
{
	if (member.dirty)
	{
		member.box = refresh();
		member.dirty = false;
		member.dirtySpace = true;
	}
}

BBox BShape::refresh()
{
	return BBox();
}
void BShape::render(BRender& render)
{

}
